import { _decorator, Component, EventTouch, Node, Prefab, random, tween, v3, Vec2, Vec3 } from 'cc';
import { PoolManager } from './PoolManager';
import { PingPongItem } from './PingPongItem';
import { EventManager, MyEvent } from './EventManager';
const { ccclass, property } = _decorator;

@ccclass('PingPongManager')
export class PingPongManager extends Component {

    public static Instance: PingPongManager = null;

    @property(Prefab)
    ItemPrefab: Prefab = null;

    @property(Node)
    BatLeft: Node = null;

    @property(Node)
    BatRight: Node = null;

    @property(Vec2)
    LeftUp: Vec2 = null;

    @property(Vec2)
    RightDown: Vec2 = null;

    @property
    BatSpeed: number = 10;

    @property
    BatHeight: number = 50;

    @property
    MaxCount: number = 1000;

    @property
    ItemRadius: number = 10;

    @property
    ItemDirX: number = 0.5;

    @property
    ItemSpeed: number = 10;

    @property(Node)
    AredNode: Node = null;

    @property(Node)
    StartNode: Node = null;

    private _dirY: number = 1;
    private _curCount: number = 0;

    private _time: number = 0;//一个循环的时间
    private _itemPosX: number[] = [];
    private _isPause: boolean = false;
    public IsStart: boolean = false;

    protected onLoad(): void {
        PingPongManager.Instance = this;

        PoolManager.Instance.preload(this.ItemPrefab, this.MaxCount);
        this.AredNode.once(Node.EventType.TOUCH_START, this.onTouchStart, this);
        tween(this.StartNode)
            .to(1, { scale: v3(1.2, 1.2, 1.2) }, { easing: `sineIn` })
            .to(1, { scale: v3(1, 1, 1) }, { easing: `sineIn` })
            .union()
            .repeatForever()
            .start();
    }

    protected start(): void {
        this._time = 2 * (this.LeftUp.y - this.RightDown.y - this.BatHeight) / this.BatSpeed;
        this.addItem(390);
    }

    protected update(dt: number): void {
        if (!this.IsStart) return;
        if (this._isPause) return;
        const move: number = this._dirY * dt * this.BatSpeed;

        const batLeftPos: Vec3 = this.BatLeft.getPosition();
        let y = batLeftPos.y + move;
        if (y >= this.LeftUp.y - this.BatHeight / 2) {
            y = this.LeftUp.y - this.BatHeight / 2 - y % (this.LeftUp.y - this.BatHeight / 2);
            this._dirY *= -1;
        } else if (y <= this.RightDown.y + this.BatHeight / 2) {
            y = this.RightDown.y + this.BatHeight / 2 - y % (this.RightDown.y + this.BatHeight / 2);
            this._dirY *= -1;
        }
        this.BatLeft.setPosition(v3(batLeftPos.x, y, batLeftPos.z));
        this.BatRight.setPosition(v3(-batLeftPos.x, - y, batLeftPos.z));

        if (this._itemPosX.length > 0) {
            const x: number = this._itemPosX.shift();
            const targetPos: Vec3 = new Vec3(x, 0, 0);
            targetPos.y = x < 0 ? this.BatLeft.getPosition().y : this.BatRight.getPosition().y;
            targetPos.z = this.BatLeft.getPosition().z;
            this.createItem(targetPos);
        }
    }

    createItem(pos: Vec3) {
        const item: Node = PoolManager.Instance.get(this.ItemPrefab);
        item.getComponent(PingPongItem).init(this.node, pos, this.ItemRadius, this.getDir(pos), this.ItemSpeed);
    }

    addItem(x: number) {
        if (this._curCount > this.MaxCount) return;
        this._curCount++;
        this._itemPosX.push(x);
    }

    getDir(pos: Vec3): Vec2 {
        const time = (this.RightDown.x - this.LeftUp.x - this.ItemRadius * 2) / (this.ItemDirX * this.ItemSpeed);
        let moveY: number = 0;
        let targetY: number = 0;
        let dirX = this.ItemDirX;
        //往左
        if (pos.x >= 0) {
            dirX *= -1;
            moveY = this._dirY * this.BatSpeed * time;
            targetY = moveY + this.BatLeft.getPosition().y;
            if (targetY > this.LeftUp.y - this.BatHeight / 2) {
                targetY = 2 * (this.LeftUp.y - this.BatHeight / 2) - targetY;
            } else if (targetY < this.RightDown.y + this.BatHeight / 2) {
                targetY = 2 * (this.RightDown.y + this.BatHeight / 2) - targetY;
            }

        } else {
            moveY = -this._dirY * this.BatSpeed * time;
            targetY = moveY + this.BatRight.getPosition().y;
            if (targetY > this.LeftUp.y - this.BatHeight / 2) {
                targetY = 2 * (this.LeftUp.y - this.BatHeight / 2) - targetY;
            } else if (targetY < this.RightDown.y + this.BatHeight / 2) {
                targetY = 2 * (this.RightDown.y + this.BatHeight / 2) - targetY;
            }
        }

        let dirY: number = this.getRandomY(targetY, pos.y, time);
        // let dirY: number = (targetY - pos.y) / time;
        return new Vec2(dirX, dirY / this.ItemSpeed);
    }

    getRandomY(targetY: number, startY: number, time: number): number {
        const flag: number = random();
        if (flag < 1 / 5) {
            return (targetY - startY) / time;
        } else if (flag < 2 / 5) {
            return ((1000 - startY) - targetY) / time;
        } else if (flag < 3 / 5) {
            return ((-1000 - startY) - targetY) / time;
        } else if (flag < 4 / 5) {
            return ((-1000 - startY) - (1000 - targetY)) / time;
        } else {
            return ((1000 - startY) - (-1000 - targetY)) / time;
        }

    }

    // getDir(pos: Vec3): Vec2 {
    //     const allTime = (this.RightDown.x - this.LeftUp.x - this.ItemRadius * 2) / (this.ItemDirX * this.ItemSpeed);
    //     const time = allTime % this._time;
    //     let moveY: number = 0;
    //     let targetY: number = 0;
    //     let dirX = this.ItemDirX;
    //     //往左
    //     if (pos.x >= 0) {
    //         dirX *= -1;
    //         moveY = this._dirY * this.BatSpeed * time;
    //         targetY = moveY + this.BatLeft.getPosition().y;
    //         if (targetY > this.LeftUp.y + this.BatHeight / 2) {
    //             targetY = 2 * (this.LeftUp.y + this.BatHeight / 2) - targetY;
    //         } else if (targetY < this.RightDown.y - this.BatHeight / 2) {
    //             targetY = 2 * (this.RightDown.y - this.BatHeight / 2) - targetY;
    //         }
    //     } else {
    //         moveY = -this._dirY * this.BatSpeed * time;
    //         targetY = moveY + this.BatRight.getPosition().y;
    //         if (targetY > this.LeftUp.y + this.BatHeight / 2) {
    //             targetY = 2 * (this.LeftUp.y + this.BatHeight / 2) - targetY;
    //         } else if (targetY < this.RightDown.y - this.BatHeight / 2) {
    //             targetY = 2 * (this.RightDown.y - this.BatHeight / 2) - targetY;
    //         }
    //     }

    //     let dirY: number = (targetY - pos.y) / allTime;
    //     return new Vec2(dirX, dirY);
    // }

    private pause() {
        this._isPause = !this._isPause;
    }

    protected onEnable(): void {
        EventManager.on(MyEvent.PAUSE, this.pause, this);
    }

    protected onDisable(): void {
        EventManager.off(MyEvent.PAUSE, this.pause, this);
    }

    onTouchStart(event: EventTouch) {
        this.IsStart = true;
        this.AredNode.active = false;
    }

}


